/**
 * Project Name:MyTookit
 * Package Name:com.xuwei.utils.db
 * author:David
 * Date:2016年6月2日上午8:58:16
 * Copyright (c) 2016, xw123box@126.com All Rights Reserved.
 *
 */
package com.xuwei.utils.db;

import java.io.InputStream;
import java.io.PrintWriter;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.logging.Logger;

import javax.sql.DataSource;

/**
 * 一个标准的数据源
 * @author David
 * @since 2016年6月2日 上午8:58:16
 * @version 
 * @since JDK 1.6
 */
public class MyDataSource implements DataSource{
	private static String driverClassName;
	private static String url;
	private static String user;
	private static String password;
	private static LinkedList<Connection> pool = new LinkedList<Connection>();//存储连接的池
	static{
		try {
			InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream("dbinfo.properties");
			Properties props = new Properties();
			props.load(in);
			driverClassName = props.getProperty("className");
			url = props.getProperty("url");
			user = props.getProperty("user");
			password = props.getProperty("password");
			Class.forName(driverClassName);
			
			//初始化10个连接到池中
			for(int i=0;i<10;i++){
				Connection conn = DriverManager.getConnection(url, user, password);
				pool.add(conn);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public PrintWriter getLogWriter() throws SQLException {
		
		return null;
	}

	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
		
		
	}

	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
		
		
	}

	@Override
	public int getLoginTimeout() throws SQLException {
		
		return 0;
	}

	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		
		return null;
	}

	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		
		return null;
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		
		return false;
	}

	@Override
	public Connection getConnection() throws SQLException {
		if(pool.size()>0){
			Connection conn = pool.remove();
			MyConnection mconn = new MyConnection(conn,pool);
			return mconn;
		}else{
			throw new RuntimeException("服务器比较忙碌！");
		}
	}

	//从池中获取一个连接
	@Override
	public Connection getConnection(String username, String password)
			throws SQLException {
		if(!(this.user.equals(username)&&this.password.equals(password))){
			throw new RuntimeException("用户名或密码不匹配！");
		}
		
		if(pool.size()>0){
			Connection conn = pool.remove();
			MyConnection mconn = new MyConnection(conn,pool);
			return mconn;
		}else{
			throw new RuntimeException("服务器比较忙碌！");
		}
	}

	/**
	 * 通过继承默认适配器的包装设计模式
	 * a、编写一个类，继承默认的适配器
	 * b、定义一个引用，记住被改写类的实例
	 * c、定义构造方法，传入被改写类的实例
	 * d、对于要改写的方法，改写即可
	 * 改写com.mysql.jdbc.Connection中的close方法，在调用时，不是关闭连接而是返回池中
	 * @author wzhting
	 */
	private class MyConnection extends ConnectionWrapper {
		private Connection conn;
		private LinkedList<Connection> pool;
		public MyConnection(Connection conn,LinkedList<Connection> pool){
			super(conn);
			this.conn = conn;
			this.pool = pool;
		}
		@Override
		public void close() throws SQLException {
			pool.add(conn);
		}
		
	}
	
	/**
	 * 包装类
	 * 全部调用原有对象的原有方法。没有做任何的功能上的改变
	 * 此类便是一个默认适配器
	 */
	private class ConnectionWrapper implements Connection {
		private Connection conn;
		public ConnectionWrapper(Connection conn){
			this.conn = conn;
		}
		@Override
		public void clearWarnings() throws SQLException {
			conn.clearWarnings();
		}

		@Override
		public void close() throws SQLException {
			conn.close();
		}

		@Override
		public void commit() throws SQLException {
			conn.commit();
		}

		@Override
		public Array createArrayOf(String typeName, Object[] elements)
				throws SQLException {
			
			return null;
		}

		@Override
		public Blob createBlob() throws SQLException {
			
			return null;
		}

		@Override
		public Clob createClob() throws SQLException {
			
			return null;
		}

		@Override
		public NClob createNClob() throws SQLException {
			
			return null;
		}

		@Override
		public SQLXML createSQLXML() throws SQLException {
			
			return null;
		}

		@Override
		public Statement createStatement() throws SQLException {
			
			return null;
		}

		@Override
		public Statement createStatement(int resultSetType, int resultSetConcurrency)
				throws SQLException {
			
			return null;
		}

		@Override
		public Statement createStatement(int resultSetType,
				int resultSetConcurrency, int resultSetHoldability)
				throws SQLException {
			
			return null;
		}

		@Override
		public Struct createStruct(String typeName, Object[] attributes)
				throws SQLException {
			
			return null;
		}

		@Override
		public boolean getAutoCommit() throws SQLException {
			
			return false;
		}

		@Override
		public String getCatalog() throws SQLException {
			
			return null;
		}

		@Override
		public Properties getClientInfo() throws SQLException {
			
			return null;
		}

		@Override
		public String getClientInfo(String name) throws SQLException {
			
			return null;
		}

		@Override
		public int getHoldability() throws SQLException {
			
			return 0;
		}

		@Override
		public DatabaseMetaData getMetaData() throws SQLException {
			
			return null;
		}

		@Override
		public int getTransactionIsolation() throws SQLException {
			
			return 0;
		}

		@Override
		public Map<String, Class<?>> getTypeMap() throws SQLException {
			
			return null;
		}

		@Override
		public SQLWarning getWarnings() throws SQLException {
			
			return null;
		}

		@Override
		public boolean isClosed() throws SQLException {
			
			return false;
		}

		@Override
		public boolean isReadOnly() throws SQLException {
			
			return false;
		}

		@Override
		public boolean isValid(int timeout) throws SQLException {
			
			return false;
		}

		@Override
		public String nativeSQL(String sql) throws SQLException {
			
			return null;
		}

		@Override
		public CallableStatement prepareCall(String sql) throws SQLException {
			
			return null;
		}

		@Override
		public CallableStatement prepareCall(String sql, int resultSetType,
				int resultSetConcurrency) throws SQLException {
			
			return null;
		}

		@Override
		public CallableStatement prepareCall(String sql, int resultSetType,
				int resultSetConcurrency, int resultSetHoldability)
				throws SQLException {
			
			return null;
		}

		@Override
		public PreparedStatement prepareStatement(String sql) throws SQLException {
			
			return null;
		}

		@Override
		public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
				throws SQLException {
			
			return null;
		}

		@Override
		public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
				throws SQLException {
			
			return null;
		}

		@Override
		public PreparedStatement prepareStatement(String sql, String[] columnNames)
				throws SQLException {
			
			return null;
		}

		@Override
		public PreparedStatement prepareStatement(String sql, int resultSetType,
				int resultSetConcurrency) throws SQLException {
			
			return null;
		}

		@Override
		public PreparedStatement prepareStatement(String sql, int resultSetType,
				int resultSetConcurrency, int resultSetHoldability)
				throws SQLException {
			
			return null;
		}

		@Override
		public void releaseSavepoint(Savepoint savepoint) throws SQLException {
			

		}

		@Override
		public void rollback() throws SQLException {
			

		}

		@Override
		public void rollback(Savepoint savepoint) throws SQLException {
			

		}

		@Override
		public void setAutoCommit(boolean autoCommit) throws SQLException {
			

		}

		@Override
		public void setCatalog(String catalog) throws SQLException {
			

		}

		@Override
		public void setClientInfo(Properties properties)
				throws SQLClientInfoException {
			

		}

		@Override
		public void setClientInfo(String name, String value)
				throws SQLClientInfoException {
			

		}

		@Override
		public void setHoldability(int holdability) throws SQLException {
			

		}

		@Override
		public void setReadOnly(boolean readOnly) throws SQLException {
			

		}

		@Override
		public Savepoint setSavepoint() throws SQLException {
			
			return null;
		}

		@Override
		public Savepoint setSavepoint(String name) throws SQLException {
			
			return null;
		}

		@Override
		public void setTransactionIsolation(int level) throws SQLException {
			

		}

		@Override
		public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
			

		}

		@Override
		public boolean isWrapperFor(Class<?> iface) throws SQLException {
			
			return false;
		}

		@Override
		public <T> T unwrap(Class<T> iface) throws SQLException {
			
			return null;
		}
		@Override
		public void setSchema(String schema) throws SQLException {
			
			
		}
		@Override
		public String getSchema() throws SQLException {
			
			return null;
		}
		@Override
		public void abort(Executor executor) throws SQLException {
			
			
		}
		@Override
		public void setNetworkTimeout(Executor executor, int milliseconds)
				throws SQLException {
			
			
		}
		@Override
		public int getNetworkTimeout() throws SQLException {
			
			return 0;
		}

	}

}
